use std::fmt;

use from_pest::FromPest;
use pest::iterators;
use pest_ast::FromPest;
use tracing::debug;
use tracing::trace;

use crate::ast_define::MetaInfo;
use crate::ast_define::Rule;
use crate::ast_define::algebraic_expr::*;
use crate::ast_define::get_meta_info;
use crate::ast_define::operator::*;

// * 逻辑或表达式 LOrExp -> LAndExp | LOrExp '||' LAndExp
#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::LOrExpRecursiveMove))]
pub struct LOrExpRecursiveMove {
    pub or: OR,
    pub l_and_exp: LAndExp,
    pub l_or_exp_recursive_move: Box<Option<LOrExpRecursiveMove>>,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for LOrExpRecursiveMove {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.l_or_exp_recursive_move.as_ref() {
            Some(this) => write!(f, "{} {} {}", self.or, self.l_and_exp, this),
            None => write!(f, "{} {}", self.or, self.l_and_exp),
        }
    }
}

#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::OR_LAndExp))]
pub struct OR_LAndExp {
    pub or: OR,
    pub l_and_exp: LAndExp,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for OR_LAndExp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} {}", self.or, self.l_and_exp)
    }
}

#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::LAndExp_LOrExpRecursiveMove))]
pub struct LAndExp_LOrExpRecursiveMove {
    pub l_and_exp: LAndExp,
    pub l_or_exp_recursive_move: Option<LOrExpRecursiveMove>,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for LAndExp_LOrExpRecursiveMove {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.l_or_exp_recursive_move.as_ref() {
            Some(this) => write!(f, "{} {}", self.l_and_exp, this),
            None => write!(f, "{}", self.l_and_exp),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum LOrExp {
    OR_LAndExp(Box<OR_LAndExp>),
    LAndExp_LOrExpRecursiveMove(Box<LAndExp_LOrExpRecursiveMove>),
}

impl fmt::Display for LOrExp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            LOrExp::OR_LAndExp(this) => write!(f, "{this}"),
            LOrExp::LAndExp_LOrExpRecursiveMove(this) => write!(f, "{this}"),
        }
    }
}

impl<'pest> FromPest<'pest> for LOrExp {
    type Rule = Rule;
    type FatalError = from_pest::Void;
    #[tracing::instrument(skip_all)]
    fn from_pest(
        pest: &mut iterators::Pairs<'pest, Rule>,
    ) -> Result<Self, from_pest::ConversionError<from_pest::Void>> {
        trace!("正在解析 LOrExp");
        let pair = pest.next().ok_or(from_pest::ConversionError::NoMatch)?;
        trace!("pair in LOrExp:\n{pair:#?}");
        let Rule::LOrExp = pair.as_rule() else {
            trace!("\n{:#?} != Rule::LOrExp", pair.as_rule());
            return Err(from_pest::ConversionError::NoMatch);
        };

        let mut inner = pair.into_inner();
        trace!("inner:\n{inner:#?}");
        let inner_pair = inner.peek().ok_or(from_pest::ConversionError::NoMatch)?;
        trace!("inner_pair:\n{inner_pair:#?}");
        match inner_pair.as_rule() {
            Rule::OR_LAndExp => Ok(LOrExp::OR_LAndExp(Box::new(OR_LAndExp::from_pest(
                &mut inner,
            )?))),
            Rule::LAndExp_LOrExpRecursiveMove => Ok(LOrExp::LAndExp_LOrExpRecursiveMove(Box::new(
                LAndExp_LOrExpRecursiveMove::from_pest(&mut inner)?,
            ))),
            _ => Err(from_pest::ConversionError::NoMatch),
        }
    }
}

// * 逻辑与表达式 LAndExp -> EqExp | LAndExp '&&' EqExp
#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::LAndExpRecursiveMove))]
pub struct LAndExpRecursiveMove {
    pub and: AND,
    pub eq_exp: EqExp,
    pub l_and_exp_recursive_move: Box<Option<LAndExpRecursiveMove>>,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for LAndExpRecursiveMove {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.l_and_exp_recursive_move.as_ref() {
            Some(this) => write!(f, "{} {} {}", self.and, self.eq_exp, this),
            None => write!(f, "{} {}", self.and, self.eq_exp),
        }
    }
}

#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::AND_EqExp))]
pub struct AND_EqExp {
    pub and: AND,
    pub eq_exp: EqExp,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for AND_EqExp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} {}", self.and, self.eq_exp)
    }
}

#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::EqExp_LAndExpRecursiveMove))]
pub struct EqExp_LAndExpRecursiveMove {
    pub eq_exp: EqExp,
    pub l_and_exp_recursive_move: Option<LAndExpRecursiveMove>,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for EqExp_LAndExpRecursiveMove {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.l_and_exp_recursive_move.as_ref() {
            Some(this) => write!(f, "{} {}", self.eq_exp, this),
            None => write!(f, "{}", self.eq_exp),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum LAndExp {
    AND_EqExp(Box<AND_EqExp>),
    EqExp_LAndExpRecursiveMove(Box<EqExp_LAndExpRecursiveMove>),
}

impl fmt::Display for LAndExp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            LAndExp::AND_EqExp(this) => write!(f, "{this}"),
            LAndExp::EqExp_LAndExpRecursiveMove(this) => write!(f, "{this}"),
        }
    }
}

impl<'pest> FromPest<'pest> for LAndExp {
    type Rule = Rule;
    type FatalError = from_pest::Void;
    #[tracing::instrument(skip_all)]
    fn from_pest(
        pest: &mut iterators::Pairs<'pest, Rule>,
    ) -> Result<Self, from_pest::ConversionError<from_pest::Void>> {
        trace!("正在解析 LAndExp");
        let pair = pest.next().ok_or(from_pest::ConversionError::NoMatch)?;
        trace!("pair in LAndExp:\n{pair:#?}");
        let Rule::LAndExp = pair.as_rule() else {
            trace!("\n{:#?} != Rule::LAndExp", pair.as_rule());
            return Err(from_pest::ConversionError::NoMatch);
        };

        let mut inner = pair.into_inner();
        trace!("inner:\n{inner:#?}");
        let inner_pair = inner.peek().ok_or(from_pest::ConversionError::NoMatch)?;
        trace!("inner_pair:\n{inner_pair:#?}");
        match inner_pair.as_rule() {
            Rule::AND_EqExp => Ok(LAndExp::AND_EqExp(Box::new(AND_EqExp::from_pest(
                &mut inner,
            )?))),
            Rule::EqExp_LAndExpRecursiveMove => Ok(LAndExp::EqExp_LAndExpRecursiveMove(Box::new(
                EqExp_LAndExpRecursiveMove::from_pest(&mut inner)?,
            ))),
            _ => Err(from_pest::ConversionError::NoMatch),
        }
    }
}

// * 相等性表达式 EqExp -> RelExp | EqExp ('==' | '!=') RelExp

#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::EqExpRecursiveMove))]
pub struct EqExpRecursiveMove {
    pub equality_operator: EqualityOperator,
    pub rel_exp: RelExp,
    pub eq_exp_recursive_move: Box<Option<EqExpRecursiveMove>>,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for EqExpRecursiveMove {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.eq_exp_recursive_move.as_ref() {
            Some(this) => write!(f, "{} {} {}", self.equality_operator, self.rel_exp, this),
            None => write!(f, "{} {}", self.equality_operator, self.rel_exp),
        }
    }
}

#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::EqualityOperator_RelExp))]
pub struct EqualityOperator_RelExp {
    pub equality_operator: EqualityOperator,
    pub rel_exp: RelExp,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for EqualityOperator_RelExp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} {}", self.equality_operator, self.rel_exp)
    }
}

#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::RelExp_EqExpRecursiveMove))]
pub struct RelExp_EqExpRecursiveMove {
    pub rel_exp: RelExp,
    pub eq_exp_recursive_move: Option<EqExpRecursiveMove>,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for RelExp_EqExpRecursiveMove {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.eq_exp_recursive_move.as_ref() {
            Some(this) => write!(f, "{} {}", self.rel_exp, this),
            None => write!(f, "{}", self.rel_exp),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum EqExp {
    EqualityOperator_RelExp(Box<EqualityOperator_RelExp>),
    RelExp_EqExpRecursiveMove(Box<RelExp_EqExpRecursiveMove>),
}

impl fmt::Display for EqExp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            EqExp::EqualityOperator_RelExp(this) => write!(f, "{this}"),
            EqExp::RelExp_EqExpRecursiveMove(this) => write!(f, "{this}"),
        }
    }
}

impl<'pest> FromPest<'pest> for EqExp {
    type Rule = Rule;
    type FatalError = from_pest::Void;
    #[tracing::instrument(skip_all)]
    fn from_pest(
        pest: &mut iterators::Pairs<'pest, Rule>,
    ) -> Result<Self, from_pest::ConversionError<from_pest::Void>> {
        trace!("正在解析 EqExp");
        let pair = pest.next().ok_or(from_pest::ConversionError::NoMatch)?;
        trace!("pair in EqExp:\n{pair:#?}");
        let Rule::EqExp = pair.as_rule() else {
            trace!("\n{:#?} != Rule::EqExp", pair.as_rule());
            return Err(from_pest::ConversionError::NoMatch);
        };

        let mut inner = pair.into_inner();
        trace!("inner:\n{inner:#?}");
        let inner_pair = inner.peek().ok_or(from_pest::ConversionError::NoMatch)?;
        trace!("inner_pair:\n{inner_pair:#?}");
        match inner_pair.as_rule() {
            Rule::EqualityOperator_RelExp => Ok(EqExp::EqualityOperator_RelExp(Box::new(
                EqualityOperator_RelExp::from_pest(&mut inner)?,
            ))),
            Rule::RelExp_EqExpRecursiveMove => Ok(EqExp::RelExp_EqExpRecursiveMove(Box::new(
                RelExp_EqExpRecursiveMove::from_pest(&mut inner)?,
            ))),
            _ => Err(from_pest::ConversionError::NoMatch),
        }
    }
}

// * 关系表达式 RelExp -> AddExp | RelExp ( '<=' | '>=' | '<' | '>' ) AddExp
#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::RelExpRecursiveMove))]
pub struct RelExpRecursiveMove {
    pub relation_operator: RelationOperator,
    pub add_exp: AddExp,
    pub rel_exp_recursive_move: Box<Option<RelExpRecursiveMove>>,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for RelExpRecursiveMove {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.rel_exp_recursive_move.as_ref() {
            Some(this) => write!(f, "{} {} {}", self.relation_operator, self.add_exp, this),
            None => write!(f, "{} {}", self.relation_operator, self.add_exp),
        }
    }
}

#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::RelationOperator_AddExp))]
pub struct RelationOperator_AddExp {
    pub relation_operator: RelationOperator,
    pub add_exp: AddExp,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for RelationOperator_AddExp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} {}", self.relation_operator, self.add_exp)
    }
}

#[derive(Debug, PartialEq, FromPest)]
#[pest_ast(rule(Rule::AddExp_RelExpRecursiveMove))]
pub struct AddExp_RelExpRecursiveMove {
    pub add_exp: AddExp,
    pub rel_exp_recursive_move: Option<RelExpRecursiveMove>,
    #[pest_ast(outer(with(get_meta_info)))]
    pub meta_info: MetaInfo,
}

impl fmt::Display for AddExp_RelExpRecursiveMove {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.rel_exp_recursive_move.as_ref() {
            Some(this) => write!(f, "{} {}", self.add_exp, this),
            None => write!(f, "{}", self.add_exp),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum RelExp {
    RelationOperator_AddExp(RelationOperator_AddExp),
    AddExp_RelExpRecursiveMove(AddExp_RelExpRecursiveMove),
}

impl fmt::Display for RelExp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            RelExp::RelationOperator_AddExp(this) => write!(f, "{this}"),
            RelExp::AddExp_RelExpRecursiveMove(this) => write!(f, "{this}"),
        }
    }
}

impl<'pest> FromPest<'pest> for RelExp {
    type Rule = Rule;
    type FatalError = from_pest::Void;
    #[tracing::instrument(skip_all)]
    fn from_pest(
        pest: &mut iterators::Pairs<'pest, Rule>,
    ) -> Result<Self, from_pest::ConversionError<from_pest::Void>> {
        trace!("正在解析 RelExp");
        let pair = pest.next().ok_or(from_pest::ConversionError::NoMatch)?;
        trace!("pair in RelExp:\n{pair:#?}");
        let Rule::RelExp = pair.as_rule() else {
            trace!("\n{:#?} != Rule::RelExp", pair.as_rule());
            return Err(from_pest::ConversionError::NoMatch);
        };

        let mut inner = pair.into_inner();
        trace!("inner:\n{inner:#?}");
        let inner_pair = inner.peek().ok_or(from_pest::ConversionError::NoMatch)?;
        trace!("inner_pair:\n{inner_pair:#?}");
        match inner_pair.as_rule() {
            Rule::RelationOperator_AddExp => Ok(RelExp::RelationOperator_AddExp(
                RelationOperator_AddExp::from_pest(&mut inner)?,
            )),
            Rule::AddExp_RelExpRecursiveMove => Ok(RelExp::AddExp_RelExpRecursiveMove(
                AddExp_RelExpRecursiveMove::from_pest(&mut inner)?,
            )),
            _ => Err(from_pest::ConversionError::NoMatch),
        }
    }
}
